package com.rtline.business.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.rtline.business.listener.UserDataListener;
import com.rtline.business.model.UserEntity;
import com.rtline.business.service.UserService;
import com.rtline.business.vo.UserVo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import cn.hutool.core.collection.CollUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;


@RestController
@RequestMapping("/file")
@Slf4j
public class FileController {


    @Autowired
    private ThreadPoolExecutor taskExecutor;

    @Autowired
    private UserService userService;

    /**
     * 多线程实现百万导出到excel 50s优化到11s
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws IOException {
        OutputStream outputStream = response.getOutputStream();
        long start = System.currentTimeMillis();
        System.out.println("-----------任务执行开始-----------");
        // 设置响应内容
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("UTF-8");// 防止下载的文件名字乱码
        try {
            // 文件以附件形式下载
            response.setHeader("Content-disposition", "attachment;filename=down_" + URLEncoder.encode(System.currentTimeMillis() + ".xlsx", "utf-8"));
            //获取总数据量
            int count = 5;
            //每页多少个
            int pageSize = 5;
            //必须放到循环外，否则会刷新流
            ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
            List<CompletableFuture> completableFutures = new ArrayList<>();
            for (int i = 0; i < (count / pageSize) + 1; i++) {
                int finalI = i;
                CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                    List<UserEntity> exportList = userService.findLimit(finalI * pageSize, pageSize);
                    if (!CollectionUtils.isEmpty(exportList)) {
                        WriteSheet writeSheet = EasyExcel.writerSheet(finalI, "用户" + (finalI + 1)).head(UserEntity.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
                        synchronized (excelWriter) {
                            excelWriter.write(exportList, writeSheet);
                        }
                    }
                }, taskExecutor);
                completableFutures.add(completableFuture);
            }
            for (CompletableFuture completableFuture : completableFutures) {
                completableFuture.join();
            }
            //刷新流
            excelWriter.finish();

            System.out.println("本次导出execl任务执行完毕,共消耗：  " + (System.currentTimeMillis() - start) + "ms");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        outputStream.flush();
        response.getOutputStream().close();
    }

    @PostMapping("/import")
    public String importExcel(@RequestParam("file") MultipartFile file) throws IOException {

        //常规实现
        // UserDataListener listener = new UserDataListener(userService);
        // EasyExcel.read(file.getInputStream(), UserVo.class, listener).sheet().doRead();
        // return "导入成功";

        //Callable实现
        // List<Callable<Object>> tasks = new ArrayList<>();
        // int sheetCount = EasyExcel.read(file.getInputStream()).build()
        //         .excelExecutor()
        //         .sheetList()
        //         .size();
        // System.out.println("Sheet页数量: " + sheetCount);
        //
        // for (int i = 0; i < sheetCount; i++) {
        //     int num = i;
        //     tasks.add(() -> {
        //         UserDataListener listener = new UserDataListener(userService);
        //         EasyExcel.read(file.getInputStream(), UserVo.class, listener)
        //                 .sheet(num)
        //                 .doRead();
        //         List<String> errorMessages = listener.getErrorMessages();
        //         if (!errorMessages.isEmpty()) {
        //             return CollUtil.join(errorMessages, "\n");
        //         }
        //         return null;
        //     });
        // }
        // try {
        //     Executors.newFixedThreadPool(sheetCount).invokeAll(tasks);
        // } catch (InterruptedException e) {
        //     throw new RuntimeException(e);
        // }
        // return "导入完成";

        // 获取Sheet页数量
        int sheetCount = EasyExcel.read(file.getInputStream()).build()
                .excelExecutor()
                .sheetList()
                .size();
        System.out.println("Sheet页数量: " + sheetCount);

        // 创建任务列表
        List<CompletableFuture<Object>> futures = new ArrayList<>();
        for (int i = 0; i < sheetCount; i++) {
            int num = i;
            futures.add(CompletableFuture.supplyAsync(() -> {
                UserDataListener listener = new UserDataListener(userService);
                try {
                    EasyExcel.read(file.getInputStream(), UserVo.class, listener)
                            .sheet(num)
                            .doRead();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                List<String> errorMessages = listener.getErrorMessages();
                if (!errorMessages.isEmpty()) {
                    return CollUtil.join(errorMessages, "\n");
                }
                return null;
            }));
        }

        // 等待所有任务完成并收集结果
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0]));

        // 获取所有任务的结果
        CompletableFuture<List<Object>> allResultsFuture = allFutures.thenApply(v -> {
            List<Object> results = new ArrayList<>();
            for (CompletableFuture<Object> future : futures) {
                try {
                    results.add(future.get());
                } catch (InterruptedException | ExecutionException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
            }
            return results;
        });

        List<Object> results = null;
        try {
            results = allResultsFuture.get();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        // 检查是否有错误信息
        StringBuilder errorMessages = new StringBuilder();
        for (Object result : results) {
            if (result != null) {
                errorMessages.append(result).append("\n");
            }
        }

        if (errorMessages.length() > 0) {
            return "导入数据存在以下错误：\n" + errorMessages.toString();
        } else {
            return "导入完成";
        }
    }
}
